<?php
/**
 * Created by PhpStorm.
 * @author WYZ <wyz@jungo.com.cn>
 * @copyright 深圳市俊网网络有限公司
 */

namespace Selibra\Redis;


use Co\Channel;
use Monolog\Logger;
use RuntimeException;
use Selibra\Config\Config;
use Selibra\Log\Log;
use Selibra\Tools\Console;
use Swoole\Lock;
use Swoole\Database\RedisConfig;

class RedisPool
{


    /**
     * @var \Swoole\Database\RedisPool
     */
    protected \Swoole\Database\RedisPool $pool;


    /**
     * @var self
     */
    protected static self $ins;


    /**
     * @return array|RedisPool
     */
    public static function getIns($config = [])
    {
        if (!isset(self::$ins)) {
            self::$ins = new self($config);
        }
        return self::$ins;
    }


    /**
     * RedisPool constructor.
     * @param array $config
     */
    private function __construct($config = [])
    {
        $config = array_merge(Config::get('application.redis'), $config);
        if (!isset($this->pool)) {
            try {
                $this->pool = new \Swoole\Database\RedisPool((new RedisConfig)
                    ->withHost($config['host'])
                    ->withPort($config['port'])
                    ->withTimeout(60)
                    ->withAuth($config['auth'] ?? '')
                    ->withDbIndex($config['dbIndex'] ?? 0)
                    ->withTimeout($config['timeOut'] ?? 1)
                    ->withReadTimeout($config['readTimeOut'] ?? 2)
                    ->withRetryInterval($config['retryInterval'] ?? 3)
                    , $config['pool_size']
                );
            } catch (\Throwable $exception) {
                Log::record($exception, Logger::ERROR);
            }

        }

    }


    /**
     * @return Redis
     */
    public function get()
    {
        $redis = $this->pool->get();
        if (false === $redis) {
            $this->pool->put(null);
            throw new RuntimeException("Pop redis timeout");
        }
        defer(function () use ($redis) { //释放
            $this->pool->put($redis);
        });
        return $redis;
    }

}
